// Package config 提供配置服务的客户端实现
//
// 该包提供了一套统一的接口，用于访问配置服务（config_server）：
// 1. 配置获取和更新
//   - LoadConfigs：获取完整配置
//   - UpdateAllConfigs：更新完整配置
//   - UpdateConfig：更新单条配置
//   - GetConfigsByPrefix：获取指定前缀的配置项
//
// 2. 配置展示和调试
//   - PrintConfigs：按项打印配置内容
//
// API 端点说明：
//   - POST /api/v1/configs/get：获取完整配置
//   - POST /api/v1/configs/update/all：更新完整配置
//   - POST /api/v1/configs/update：更新单条配置
//
// 使用示例：
//
//	// 创建客户端
//	client := config.NewClient("http://localhost:8082")
//
//	// 获取完整配置
//	configs, err := client.LoadConfigs()
//	if err != nil {
//	    log.Fatal(err)
//	}
//
//	// 更新单条配置
//	err = client.UpdateConfig("mqtt.broker_address", "mqtt://new-server:1883")
//	if err != nil {
//	    log.Fatal(err)
//	}
//
//	// 更新完整配置
//	err = client.UpdateAllConfigs(configs)
//	if err != nil {
//	    log.Fatal(err)
//	}
package config

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"sort"
	"strings"
	"time"

	"gitee.com/rw555/fdsmastergo/pkg/logger"
	"go.uber.org/zap"
)

// Client 配置服务客户端
type Client struct {
	baseURL    string       // 配置服务地址
	httpClient *http.Client // HTTP客户端
}

// NewClient 创建配置服务客户端
func NewClient(baseURL string) *Client {
	return &Client{
		baseURL: baseURL,
		httpClient: &http.Client{
			Timeout: 10 * time.Second, // 设置10秒超时
		},
	}
}

// LoadConfigs 获取完整配置
func (c *Client) LoadConfigs() (map[string]interface{}, error) {
	url := fmt.Sprintf("%s/api/v1/configs/get", c.baseURL)
	resp, err := c.httpClient.Post(url, "application/json", nil)
	if err != nil {
		return nil, fmt.Errorf("获取配置失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("获取配置失败，HTTP状态码: %d", resp.StatusCode)
	}

	// 读取响应内容
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应失败: %w", err)
	}

	// 解析响应
	var response struct {
		Code    int                    `json:"code"`
		Message string                 `json:"message"`
		Data    map[string]interface{} `json:"data"`
	}
	if err := json.Unmarshal(body, &response); err != nil {
		return nil, fmt.Errorf("解析响应失败: %w", err)
	}

	// 检查响应码
	if response.Code != 0 {
		return nil, fmt.Errorf("获取配置失败: %s (错误码: %d)", response.Message, response.Code)
	}

	// 检查配置是否为空
	if response.Data == nil {
		return nil, fmt.Errorf("配置数据为空")
	}

	logger.SystemInfo("获取完整配置成功", zap.Int("配置项数量", len(response.Data)))
	return response.Data, nil
}

// UpdateAllConfigs 更新完整配置
func (c *Client) UpdateAllConfigs(configs map[string]interface{}) error {
	url := fmt.Sprintf("%s/api/v1/configs/update/all", c.baseURL)
	jsonData, err := json.Marshal(configs)
	if err != nil {
		return fmt.Errorf("序列化配置失败: %w", err)
	}

	resp, err := c.httpClient.Post(url, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("更新配置失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("更新配置失败，HTTP状态码: %d", resp.StatusCode)
	}

	// 读取响应内容
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("读取响应失败: %w", err)
	}

	// 解析响应
	var response struct {
		Code    int    `json:"code"`
		Message string `json:"message"`
	}
	if err := json.Unmarshal(body, &response); err != nil {
		return fmt.Errorf("解析响应失败: %w", err)
	}

	if response.Code != 0 {
		return fmt.Errorf("更新配置失败: %s (错误码: %d)", response.Message, response.Code)
	}

	logger.SystemInfo("更新完整配置成功", zap.Int("配置项数量", len(configs)))
	return nil
}

// UpdateConfig 更新单条配置
func (c *Client) UpdateConfig(key string, value interface{}) error {
	// 构造请求数据
	requestData := struct {
		Key   string      `json:"key"`
		Value interface{} `json:"value"`
	}{
		Key:   key,
		Value: value,
	}

	// 序列化请求数据
	jsonData, err := json.Marshal(requestData)
	if err != nil {
		return fmt.Errorf("序列化配置失败: %w", err)
	}

	// 发送更新请求
	url := fmt.Sprintf("%s/api/v1/configs/update", c.baseURL)
	resp, err := c.httpClient.Post(url, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("更新配置失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("更新配置失败，HTTP状态码: %d", resp.StatusCode)
	}

	// 读取响应内容
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("读取响应失败: %w", err)
	}

	// 解析响应
	var response struct {
		Code    int    `json:"code"`
		Message string `json:"message"`
	}
	if err := json.Unmarshal(body, &response); err != nil {
		return fmt.Errorf("解析响应失败: %w", err)
	}

	if response.Code != 0 {
		return fmt.Errorf("更新配置失败: %s (错误码: %d)", response.Message, response.Code)
	}

	logger.SystemInfo("更新单条配置成功",
		zap.String("key", key),
		zap.Any("value", value))

	return nil
}

// GetConfigsByPrefix 获取指定前缀的所有配置项
func (c *Client) GetConfigsByPrefix(configs map[string]interface{}, prefix string) map[string]interface{} {
	result := make(map[string]interface{})

	// 遍历所有配置项
	for key, value := range configs {
		// 检查键是否以指定前缀开头
		if strings.HasPrefix(key, prefix) {
			result[key] = value
		}
	}

	logger.SystemDebug("获取前缀配置成功",
		zap.String("prefix", prefix),
		zap.Int("匹配数量", len(result)))

	return result
}

// PrintConfigs 按项打印配置内容
func (c *Client) PrintConfigs(configs map[string]interface{}) {
	if len(configs) == 0 {
		logger.SystemInfo("配置为空")
		return
	}

	// 获取所有键并排序
	keys := make([]string, 0, len(configs))
	for k := range configs {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	// 打印配置总数
	logger.SystemInfo(fmt.Sprintf("配置项总数：%d", len(configs)))

	// 按分类打印配置项
	currentCategory := ""
	for _, key := range keys {
		// 获取分类（第一个点号之前的部分）
		parts := strings.Split(key, ".")
		category := parts[0]

		// 如果是新分类，打印分类标题
		if category != currentCategory {
			logger.SystemInfo(fmt.Sprintf("【%s】", category))
			currentCategory = category
		}

		// 格式化值的显示
		var valueStr string
		switch v := configs[key].(type) {
		case string:
			valueStr = fmt.Sprintf("%q", v) // 字符串加引号显示
		case nil:
			valueStr = "null"
		default:
			valueStr = fmt.Sprintf("%v", v)
		}

		// 打印配置项
		logger.SystemInfo(fmt.Sprintf("  %s = %s", key, valueStr))
	}
}

// SaveAutoModeSession 保存自动模式会话记录到数据库
func (c *Client) SaveAutoModeSession(startTime, endTime time.Time) error {
	// 准备请求数据
	requestData := map[string]interface{}{
		"start_time": startTime.Format("2006-01-02 15:04:05"),
		"end_time":   endTime.Format("2006-01-02 15:04:05"),
	}

	// 序列化请求数据
	jsonData, err := json.Marshal(requestData)
	if err != nil {
		return fmt.Errorf("序列化请求数据失败: %w", err)
	}

	// 发送POST请求到config服务
	url := fmt.Sprintf("%s/api/v1/auto-mode/sessions", c.baseURL)
	resp, err := c.httpClient.Post(
		url,
		"application/json",
		bytes.NewBuffer(jsonData),
	)
	if err != nil {
		return fmt.Errorf("发送请求到config服务失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		bodyBytes, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("config服务返回错误: %d %s", resp.StatusCode, string(bodyBytes))
	}

	// 计算持续时间（分钟）用于日志记录
	durationMinutes := int(endTime.Sub(startTime).Minutes())

	logger.OperationInfo("保存自动模式会话记录成功",
		zap.String("开始时间", startTime.Format("2006-01-02 15:04:05")),
		zap.String("结束时间", endTime.Format("2006-01-02 15:04:05")),
		zap.Int("持续时间(分钟)", durationMinutes))

	return nil
}

// GetAutoModeSessions 获取自动模式会话记录列表
func (c *Client) GetAutoModeSessions(startDate, endDate string, limit, offset int) ([]map[string]interface{}, error) {
	// 准备请求数据
	requestData := map[string]interface{}{
		"start_date": startDate,
		"end_date":   endDate,
		"limit":      limit,
		"offset":     offset,
	}

	// 序列化请求数据
	jsonData, err := json.Marshal(requestData)
	if err != nil {
		return nil, fmt.Errorf("序列化请求数据失败: %w", err)
	}

	// 发送POST请求到config服务
	url := fmt.Sprintf("%s/api/v1/auto-mode/sessions/query", c.baseURL)
	resp, err := c.httpClient.Post(
		url,
		"application/json",
		bytes.NewBuffer(jsonData),
	)
	if err != nil {
		return nil, fmt.Errorf("发送请求到config服务失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		bodyBytes, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("config服务返回错误: %d %s", resp.StatusCode, string(bodyBytes))
	}

	// 读取响应内容
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应失败: %w", err)
	}

	// 解析响应
	var response struct {
		Code    int                      `json:"code"`
		Message string                   `json:"message"`
		Data    []map[string]interface{} `json:"data"`
	}
	if err := json.Unmarshal(body, &response); err != nil {
		return nil, fmt.Errorf("解析响应失败: %w", err)
	}

	// 检查响应码
	if response.Code != 0 {
		return nil, fmt.Errorf("获取自动模式会话记录失败: %s (错误码: %d)", response.Message, response.Code)
	}

	// 处理时间字段，确保正确解析
	for _, session := range response.Data {
		// 处理时间字段
		for field, value := range session {
			if strValue, ok := value.(string); ok && (field == "start_time" || field == "end_time" || field == "created_at") {
				// 尝试解析时间字符串
				if t, err := time.Parse("2006-01-02T15:04:05Z", strValue); err == nil {
					// 如果是ISO格式，转换为标准格式
					session[field] = t.Format("2006-01-02 15:04:05")
				}
				// 如果已经是标准格式，保持不变
			}
		}
	}

	logger.OperationInfo("获取自动模式会话记录成功",
		zap.Int("记录数量", len(response.Data)),
		zap.String("开始日期", startDate),
		zap.String("结束日期", endDate))

	return response.Data, nil
}
